﻿using GalaSoft.MvvmLight.Command;
using Hue_Demo_PCL.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
using System.Runtime.Serialization;
using Hue_Demo_PCL.Models;
using System.Net;
using System.Threading;
using System.Diagnostics;

#if NETFX_CORE
using Windows.UI.Xaml;
#elif WINDOWS_PHONE
using System.Windows.Threading;
#endif


namespace Hue_Demo_Phone.ViewModels
{
    public class HueClientViewModel : HueControlViewModel
    {
        DispatcherTimer _dt;
        bool _isCycleLive = false;

        public HueClientViewModel() 
        {   
            StartupTasks();
        }

        private async void StartupTasks()
        {

            bool hasUser = await GetUserInfo();
            if (hasUser)
            {
                IsUserRegistered = true;
                await SetUser(UserName, false);
                GetLights.Execute(null);
            }
            _animateVM._hueService = GetHueService();
            DispatcherTimer _dt;
            _dt = new DispatcherTimer();
            _dt.Interval = new TimeSpan(0, 0, 0, 1);
            _dt.Tick += _dt_Tick;
            _dt.Start();
        }

#if NETFX_CORE
        void _dt_Tick(object sender, object e)  
#elif WINDOWS_PHONE
        void _dt_Tick_Win8(object sender, EventArgs e)
#endif
        {
            if (_isCycleLive)
                this.CycleLights.Execute(null);
            else
                this.GetLights.Execute(null);
        }

        #region AnimateViewModel (HueClientAnimateViewModel)
        private HueClientAnimateViewModel _animateVM = new HueClientAnimateViewModel();
        public HueClientAnimateViewModel AnimateViewModel
        {
            get { return _animateVM; }
            set
            {
                _animateVM = value;
                RaisePropertyChanged("AnimateViewModel");
            }
        }
        #endregion

        #region RegisterUser Command
        private RelayCommand _registerUserCommand;

        /// <summary>
        /// Gets the RegisterUser.
        /// This command is done in this subclass because I want to 
        ///    save the value that I get back from the service and 
        ///    that requires access to the Storage APIs which are 
        ///    not accessible in PCL libraries
        /// </summary>
        public RelayCommand RegisterUser
        {
            get
            {
                return _registerUserCommand
                    ?? (_registerUserCommand = new RelayCommand(
                    async () =>
                    {
                        if (IsWorking)
                            return;
                        IsWorking = true;
                        string userResult = await SetUser(UserName, true);
                        if (!userResult.Contains("Error:"))
                        {
                            await SaveUserInfo(userResult);
                            IsUserRegistered = true;
                            GetLights.Execute(null);
                        }
                        else
                        {
                            ConnectionError = "Could not register. Did you press the 'link' button on your Hue hub?";
                        }
                        IsWorking = false;
                    }, () => ! IsWorking));
            }
        }
        #endregion

        #region StartCycle Command
        private RelayCommand _startCycle;

        /// <summary>
        /// Gets the StartCycle.
        /// </summary>
        public RelayCommand StartCycle
        {
            get
            {
                return _startCycle
                    ?? (_startCycle = new RelayCommand(
                    () =>
                    {
                        _isCycleLive = true;
                    }));
            }
        }
        #endregion

        #region EndCycle Command
        private RelayCommand _endCycle;

        /// <summary>
        /// Gets the EndCycle.
        /// </summary>
        public RelayCommand EndCycle
        {
            get
            {
                return _endCycle
                    ?? (_endCycle = new RelayCommand(
                    () =>
                    {
                        _isCycleLive = false;
                    }));
            }
        }

        #endregion

        #region Save User Information

        // This user information will persist on the Hue hub
        private async Task SaveUserInfo(string userName)
        {
            StorageFile userNameFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("userName.txt", CreationCollisionOption.ReplaceExisting);
            var writeStream = await userNameFile.OpenStreamForWriteAsync();
            DataContractSerializer uNameS = new DataContractSerializer(typeof(string));
            uNameS.WriteObject(writeStream, userName);
            await writeStream.FlushAsync();
#if WIN_PHONE
            writeStream.Close();
#elif NETFX_CORE
            writeStream.Dispose();
#endif

        }

        private async Task<bool> GetUserInfo()
        {
            try
            {
                StorageFile uNameFile = await ApplicationData.Current.LocalFolder.GetFileAsync("userName.txt");
                using (var readStream = await uNameFile.OpenStreamForReadAsync())
                {
                    DataContractSerializer uNameS = new DataContractSerializer(typeof(string));
                    string userName = "";
                    userName = (string)uNameS.ReadObject(readStream);
#if WIN_PHONE
                    readStream.Close();
#endif
                    UserName = userName;
                    return true;
                }
            }
            catch(Exception e)
            {
                return false;
            }
        }

        #endregion

        #region Save IP Bridge Information

        // This user information will persist on the Hue hub
        private async Task SaveBridgeInfo(HueSettings ipBridgeInfo)
        {
            StorageFile bridgeFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("hueBridgeInfo.dat", CreationCollisionOption.ReplaceExisting);
            var writeStream = await bridgeFile.OpenStreamForWriteAsync();
            DataContractSerializer uNameS = new DataContractSerializer(typeof(HueSettings));
            uNameS.WriteObject(writeStream, ipBridgeInfo);
            await writeStream.FlushAsync();
#if WIN_PHONE
            writeStream.Close();
#elif NETFX_CORE
            writeStream.Dispose();
#endif
        }

        private async Task<HueSettings> GetBridgeInfo()
        {
            try
            {
                StorageFile bridgeFile = await ApplicationData.Current.LocalFolder.GetFileAsync("hueBridgeInfo.dat");
                using (var readStream = await bridgeFile.OpenStreamForReadAsync())
                {
                    DataContractSerializer bridgeSerial = new DataContractSerializer(typeof(string));
                    HueSettings bridgeInfo = null;
                    bridgeInfo = (HueSettings)bridgeSerial.ReadObject(readStream);
#if WIN_PHONE
                    readStream.Close();
#endif
                    return bridgeInfo;
                }
            }
            catch (Exception e)
            {
                return null;
            }
        }

        #endregion
    }
}
